import 'package:equatable/equatable.dart';

/// 通用API响应模型
class ApiResponse<T> extends Equatable {
  final int code;
  final String message;
  final T? data;
  final bool success;

  const ApiResponse({
    required this.code,
    required this.message,
    this.data,
    required this.success,
  });

  factory ApiResponse.fromJson(
    Map<String, dynamic> json,
    T Function(Object? json)? fromJsonT,
  ) {
    return ApiResponse<T>(
      code: json['code'] as int,
      message: json['message'] as String,
      data: json['data'] != null && fromJsonT != null
          ? fromJsonT(json['data'])
          : json['data'] as T?,
      success: (json['code'] as int) == 200,
    );
  }

  Map<String, dynamic> toJson(Object Function(T value)? toJsonT) {
    return {
      'code': code,
      'message': message,
      'data': data != null && toJsonT != null ? toJsonT(data as T) : data,
    };
  }

  /// 创建成功响应
  factory ApiResponse.success({
    String message = '操作成功',
    T? data,
  }) {
    return ApiResponse<T>(
      code: 200,
      message: message,
      data: data,
      success: true,
    );
  }

  /// 创建错误响应
  factory ApiResponse.error({
    required int code,
    required String message,
    T? data,
  }) {
    return ApiResponse<T>(
      code: code,
      message: message,
      data: data,
      success: false,
    );
  }

  @override
  List<Object?> get props => [code, message, data, success];

  @override
  String toString() {
    return 'ApiResponse{code: $code, message: $message, success: $success, data: $data}';
  }
}

/// 分页响应模型
class PageResponse<T> extends Equatable {
  final List<T> content;
  final int totalElements;
  final int totalPages;
  final int currentPage;
  final int size;
  final bool first;
  final bool last;
  final bool hasNext;
  final bool hasPrevious;

  const PageResponse({
    required this.content,
    required this.totalElements,
    required this.totalPages,
    required this.currentPage,
    required this.size,
    required this.first,
    required this.last,
    required this.hasNext,
    required this.hasPrevious,
  });

  factory PageResponse.fromJson(
    Map<String, dynamic> json,
    T Function(Object? json) fromJsonT,
  ) {
    return PageResponse<T>(
      content: (json['content'] as List<dynamic>)
          .map((item) => fromJsonT(item))
          .toList(),
      totalElements: json['totalElements'] as int,
      totalPages: json['totalPages'] as int,
      currentPage: json['currentPage'] as int,
      size: json['size'] as int,
      first: json['first'] as bool,
      last: json['last'] as bool,
      hasNext: json['hasNext'] as bool? ?? !json['last'],
      hasPrevious: json['hasPrevious'] as bool? ?? !json['first'],
    );
  }

  Map<String, dynamic> toJson(Object Function(T value) toJsonT) {
    return {
      'content': content.map((item) => toJsonT(item)).toList(),
      'totalElements': totalElements,
      'totalPages': totalPages,
      'currentPage': currentPage,
      'size': size,
      'first': first,
      'last': last,
      'hasNext': hasNext,
      'hasPrevious': hasPrevious,
    };
  }

  /// 是否为空
  bool get isEmpty => content.isEmpty;

  /// 是否不为空
  bool get isNotEmpty => content.isNotEmpty;

  @override
  List<Object?> get props => [
        content,
        totalElements,
        totalPages,
        currentPage,
        size,
        first,
        last,
        hasNext,
        hasPrevious,
      ];
}

/// 错误响应模型
class ErrorResponse extends Equatable {
  final int code;
  final String message;
  final String? details;
  final DateTime timestamp;
  final String? path;

  const ErrorResponse({
    required this.code,
    required this.message,
    this.details,
    required this.timestamp,
    this.path,
  });

  factory ErrorResponse.fromJson(Map<String, dynamic> json) {
    return ErrorResponse(
      code: json['code'] as int,
      message: json['message'] as String,
      details: json['details'] as String?,
      timestamp: json['timestamp'] != null
          ? DateTime.parse(json['timestamp'] as String)
          : DateTime.now(),
      path: json['path'] as String?,
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'code': code,
      'message': message,
      'details': details,
      'timestamp': timestamp.toIso8601String(),
      'path': path,
    };
  }

  @override
  List<Object?> get props => [code, message, details, timestamp, path];

  @override
  String toString() {
    return 'ErrorResponse{code: $code, message: $message, details: $details}';
  }
}

/// 网络异常模型
class NetworkException implements Exception {
  final String message;
  final int? statusCode;
  final dynamic originalError;

  const NetworkException({
    required this.message,
    this.statusCode,
    this.originalError,
  });

  @override
  String toString() {
    return 'NetworkException{message: $message, statusCode: $statusCode}';
  }
}

/// 业务异常模型
class BusinessException implements Exception {
  final String message;
  final int code;
  final dynamic data;

  const BusinessException({
    required this.message,
    required this.code,
    this.data,
  });

  @override
  String toString() {
    return 'BusinessException{code: $code, message: $message}';
  }
}
